
/* Copyright (C) 2025 sangong All Rights Reserved.
 
 File Name: client.c
 Author   : sangong
 Creation Date: 2025-06-05
 INFO     :
*/
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#include<sqlite3.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<dirent.h>
int connect_to_server(const char *ip,const char *port);
int login_register(int sockfd);
int send_buf(int sockfd);
int get_file(int sockfd);
void opt_file(int sockfd);

//文件名的指针数组
char * server_fn[1024];
int main(int argc,char *argv[])
{
     //1.连接服务器，需要传入ip地址和端口
    puts("请输入服务器的ip地址和端口号");
    char ip_buf[64]={0}; 
    char port_buf[64]={0};
    read(0,ip_buf,64);
    read(0,port_buf,64);
    ip_buf[strlen(ip_buf)-1] = '\0';
    port_buf[strlen(port_buf)-1] = '\0';
    
    int sockfd = connect_to_server(ip_buf,port_buf);

    puts("----------------------------------");
     //2.登陆注册
     login_register(sockfd);

     //3.发送消息
     //send_buf(sockfd);
    puts("----------------------------------");
     //4.获取服务器上的文件列表
   get_file(sockfd);
   fflush(stdin);
   //5.选择下载或上传文件
     opt_file(sockfd);
  // while(1);
}
//上传或下载文件
void opt_file(int sockfd){
B: puts("请选择文件操作:1下载|2上传");
  char opt_1[64] = {0};
  memset(opt_1,0,64);
  int ret = read(0,opt_1,64);
  if( ret <= 0){
    perror("read");
    exit(-1);
  }
  ret = write(sockfd,opt_1,2);
  if( ret <= 0){
    perror("write");
    exit(-1);
  }
  //处理下载功能
  if(opt_1[0] == '1'){
    puts("请输入想要下载的文件:");
    char download_fn[256] = {0};
    memset(download_fn,0,256);
    ret = read(0,download_fn,256);
    if( ret <= 0){
      perror("read");
      exit(-1);
    }
    download_fn[strlen(download_fn)-1] ='\0';
    ret = write(sockfd,download_fn,256);
    if( ret <= 0){
     perror("write");
     exit(-1);
    }
    //判断能不能下载
    char can[1] = {0};
    ret = read(sockfd,can,1);
    if( ret <= 0){
      perror("read");
      exit(-1);
    }
    if( can[0] == '1'){
      printf("正在接受文件:%s\n",download_fn);
      char fn_recv[1024];
      int fn = open(download_fn,O_CREAT|O_TRUNC|O_RDWR,0666);
      if( fn < 0){
        perror("open");
	exit(-1);
      }
      //接受文件
      while(1){
	 char size[5] = {0};
	 char buf[1024] = {0};
	 int len;
         memset(buf,0,1024);
         memset(size,0,5);
	 while( 5 >recv(sockfd,size,5,MSG_PEEK));  //先读取即将发送的数据长度（字符版）
	 recv(sockfd,size,5,0);
	 len = atoi(size);
	 while( len > recv(sockfd,buf,len,MSG_PEEK));
	 recv(sockfd,buf,len,0);
	 write(fn,buf,len);
	 if( len < 1024)
		 break;
	 }
       printf("%s下载完成\n",download_fn);
       goto B;  
      }
    else
    {
      printf("文件名错误\n");
      goto B;
    }
   }
  //选择上传
  else if(opt_1[0] == '2')
  {
     char path[64] = {0};
     char upload_fn[64] = {0};
     puts("请选择上传的文件路径目录和文件名称:");
     int ret = read(0,path,64);
     if( ret <= 0){
       perror("read");
       exit(-1);
     }
     ret = read(0,upload_fn,64);
     if( ret <= 0){
       perror("read");
       exit(-1);
     }
     path[strlen(path)-1] = '\0';
     upload_fn[strlen(upload_fn)-1] = '\0';
     //判断该路径下是否有该文件
     int find_flag = 0;
     struct dirent *file;
     DIR *dp;
     dp = opendir(path);
     while( file = readdir(dp)){
       if(strncmp(file->d_name,upload_fn,strlen(upload_fn)) ==0)
	       find_flag = 1;
     }
     //找到该文件可以进行发送
     if(find_flag){
       write(sockfd,"3",1);
       write(sockfd,upload_fn,64);
       char upload_fn_2[128] = {0};
       sprintf(upload_fn_2,"%s/%s",path,upload_fn);
       int fd = open(upload_fn_2,O_RDONLY);  
       char buf[1024] = {0};
       char buf_len[5] = {0};
       while(1){
         memset(buf,0,1024);
	 memset(buf_len,0,5);
	 ret = read(fd,buf,sizeof(buf));
	 if( ret <= 0){
	  close(fd);
	  break;
	 }
	 sprintf(buf_len,"%d",ret);
	 if( 0 >= write(sockfd,buf_len,5)){
	   perror("write");
	   break;
	 }
	 if( 0>= write(sockfd,buf,ret)){
	   perror("write");
	   break;
	 }
       }
       printf("%s上传完成\n",upload_fn);
      goto B; 
     }
     //未找到该文件
     else{
       write(sockfd,"4",1);
       puts("文件路径或文件名错误");
       goto B;
     }
  }
  //用户选择输入错误
  else
  {
    puts("请输入正确操作方式");

    goto B;
  }
  
}

int send_buf(int sockfd){
      
    int ret = 0;
    char buf[64] = {0};
    while(1){
	 memset(buf,0,64);
         ret = read(0,buf,64);
         ret = write(sockfd,buf,64);	 
    }

}

int get_file(int sockfd){
      
     char file_name[256] = {0};
     int ret;
     int num = 0;
     puts("服务器端的文件包含:");	
     while(1){ 
	char answer[1] = {0};
        ret = read(sockfd,answer,1);
        if( ret <= 0){
	  perror("read");
	  exit(-1);
	}
	//有文件
        if( answer[0] == '1'){
           ret = read(sockfd,file_name,256);
	   printf("%s  ",file_name);
	   fflush(stdin);
	}
        else
	{
	   break;
	}
     }
     printf("\n");
}
//连接到服务器，返回一个通信套接字
int connect_to_server(const char *ip,const char *port){
     
     int sockfd = socket(AF_INET,SOCK_STREAM,0);
     if( sockfd < 0){
       perror("socket");
       puts("1连接服务器不成功，请重试");
       exit(-1);
     }
    int n_port = atoi(port);
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(n_port);
    saddr.sin_addr.s_addr = inet_addr(ip);
    
    int ret = connect(sockfd,(struct sockaddr*)&saddr,sizeof saddr);
    
    if( ret != 0){
     perror("connect");
     puts("2连接服务器不成功，请重试");
    }
    else
    {
     puts("连接服务器成功");
    }

   return sockfd;

}


//用户的登陆注册操作
int login_register(int sockfd){
   
A:	puts("1登陆|2注册");
        //获取用户输入的操作
	char opt_1[2]={0};
	read(0,opt_1,2);
	int ret = 0;
       // printf("recv:%c\n",opt_1[0]); 
	
	//登陆操作
	if( opt_1[0] == '1'){
	//传给服务器此时需要登陆操作
	  ret = write(sockfd,opt_1,2);
	   if( ret <= 0){
	         puts("操作失败，请重试");
	          goto A;
              } 
         char account[64] = {0}; //账号
	 char pass[64] = {0};  //密码
	 printf("请输入账号:\n");
	 read(0,account,64);
	 account[strlen(account)-1]='\0';
	 printf("请输入密码:\n");
	 read(0,pass,64);
	 pass[strlen(pass)-1]='\0';
         //用户输入后通过sockfd发送
	 ret = write(sockfd,account,64);
	 if( ret < 0){
	     puts("error");
	     goto A;
	 }
	 ret = write(sockfd,pass,64);
	 if( ret < 0){
	     puts("error");
	     goto A;
	 }
         char answer[1]={0};
	 ret = read(sockfd,answer,1);
	 if( ret < 0){
	   perror("read");
	   goto A;
	 }
	 //如果回复1表示帐号密码都正确，进入用户空间
	 if( answer[0] == '1'){
	    puts("登陆成功");
	 }
         if( answer[0] == '2'){
	    puts("账号密码错误");
	    goto A;
	 }
	}	
	
	//注册操作
        else if( opt_1[0] == '2'){
	 //传给服务器此时需要登陆操作
    	   ret = write(sockfd,opt_1,2);
	   if( ret <= 0){
	       puts("操作失败，请重试");
	       goto A;
	  }
         char account[64] = {0}; //账号
	 char pass[64] = {0};  //密码
	 printf("请输入账号:\n");
	 read(0,account,64);
	 printf("请输入密码:\n");
	 read(0,pass,64);
	 account[strlen(account)-1]='\0';
	 pass[strlen(pass)-1]='\0';
         //用户输入后通过sockfd发送
	 ret = write(sockfd,account,64);
	 if( ret < 0){
	     puts("error");
	     goto A;
	 }
	 ret = write(sockfd,pass,64);
	 if( ret < 0){
	     puts("error");
	     goto A;
	 }
         char answer[1]={0};
	 ret = read(sockfd,answer,1);
	 if( ret < 0){
	     perror("read");
	     exit(-1);
	 }
	 if( answer[0] == '1'){
	     printf("注册成功，请填写用户名\n");
             char name[64] = {0};
	     read(0,name,64);
	     name[strlen(name)-1] = '\0';
	     ret = write(sockfd,name,64);
             goto A;
	  }
	 else{
	     printf("账号已注册，请直接登录\n");
	     goto A;
	 }
        }
       	
	else{
	 puts("请输入正确操作方式");
	 goto A;
	}
}
